
#include <immintrin.h>
#include "bits.h"

#define SIMD_CONATINER_8x64 //size_t 64 SimdSize 256
//#define AVX512_BITSTREAM
#define PARALLEL_DEGREE (sizeof(SimdSize)/sizeof(size_t))
typedef __m256i SimdSize;
typedef SimdSize SimdBitContainerType;
typedef size_t BitContainerLane;



#ifdef SIMD_CONATINER_8x64 
#define SIMD_SET1_SIZE(x) _mm256_set1_epi64x(x)
#define SIMD_LOADER_DEF(x) \
    SimdSize x = _mm256_set_epi64x(0, 1, 2, 3);
#define SIMD_LOAD_SIZE(src, loader) _mm256_i64gather_epi64(src, loader, sizeof(size_t))
#define SIMD_GATHER_SIZE(src, offset) _mm256_i64gather_epi64(src, offset, sizeof(size_t))
#define SIMD_GATHER(src, offset, scale) _mm256_i64gather_epi64(src, offset, scale)
#define SIMD_INSERT_SIZE(x, val, index) _mm256_mask_set1_epi64(x, ~((char)1 << ((index) - 1)), val)
#define SIMD_EXTRACT_SIZE(x, index) _mm256_extract_epi64(x, index)
#define SIMD_ADD_SIZE(a, b) _mm256_add_epi64(a, b)
#define SIMD_SUB_SIZE(a, b) _mm256_sub_epi64(a, b)
#define SIMD_AND_SIZE(a, b) _mm256_and_si256(a, b)
#define SIMD_OR_SIZE(a, b)  _mm256_or_si64(a, b)
#define SIMD_MIN_SIZE(a, b) _mm256_min_epi64(a, b)
#define SIMD_MAX_SIZE(a, b) _mm256_max_epi64(a, b)
#define SIMD_SRL_SIZE(a, b) _mm256_srlv_epi64(a, b)
#define SIMD_SLL_SIZE(a, b) _mm256_sllv_epi64(a, b)
#define SIMD_MULLO_SIZE(a, b) _mm256_mullo_epi64(a, b)
#define SIMD_EQ_SIZE(a, b) _mm256_cmpeq_epi64(a, b)
#ifdef AVX512_BITSTREAM 
#define SIMD_LZC_SIZE(x) _mm256_lzcnt_epi64(x)
#else
#define SIMD_LZC_SIZE(x)    \
    my_mm256_lzcnt_epi64(x) 0
#endif
#endif

